package cn.lysj.framework.base;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.lysj.framework.common.CommonConstant;

import cn.lysj.framework.common.utils.relation.RelationUtil;
import cn.lysj.framework.common.utils.pagination.PageVo;

import cn.lysj.framework.common.utils.web.ParamUtil;
import cn.lysj.framework.common.utils.web.Resp;
import cn.lysj.framework.common.utils.web.SelectItem;
import cn.lysj.framework.common.validate.Message;
import cn.lysj.framework.common.validate.annotation.Validator;
import cn.lysj.framework.common.validate.entity.Medusa;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import javax.validation.Valid;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * @author zk
 * @description 基础控制层
 * @create 2018-07-15 15:43
 **/
public abstract class BaseController <E extends BaseEntity> extends BaseContent{

    @PersistenceContext
    private EntityManager em;

    /**
     * 获取service
     * @return
     */
    @Resource
    public abstract BaseService<E> getService();

    /**
     * @author zk
     * @Description 根据ID查找
     * @date 2018-07-19 15:28
     */
    @RequestMapping(value = "/find_one",method = RequestMethod.GET)
    @ResponseBody
    public Resp findOne(String id){
        E e = getService().findOne(id);
        //填充该实体类中相关联的实体
        RelationUtil.initRelation(e,null,RelationUtil.MapType.IGNOR);
        return new Resp(e);
    }

    /**
     * @author zk
     * @Description 单表多条件分页查询 此处delFlag 默认为 1
     * @date 2018-07-19 15:29
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    @ResponseBody
    public Resp list(E entity, PageVo pageVo){
        Page<E> page = getService().list(entity,pageVo);
        for (E e : page.getContent()) {
            RelationUtil.initRelation(e,null,RelationUtil.MapType.IGNOR);
        }
        return new Resp(page);
    }

    /**
     * @author zk
     * @Description 获取所有数据
     * @date 2018-07-19 15:30
     */
    @RequestMapping(value = "/find_all",method = RequestMethod.GET)
    @ResponseBody
    public Resp findAll(){

        List<E> list = getService().findAll();
        for (E e : list) {
            RelationUtil.initRelation(e,null,RelationUtil.MapType.IGNOR);
        }
        return new Resp(list);
    }

    /**
     * @author zk
     * @Description 添加数据
     * @date 2018-07-19 15:31
     */
    @RequestMapping(value = "/save",method = RequestMethod.POST)
    @ResponseBody
    public Resp save(@Validator E entity){
        E e = getService().save(entity);
        return new Resp("保存成功");
    }

    /**
     * @author zk
     * @Description 更新数据
     * @date 2018-07-19 15:32
     */
    @RequestMapping(value = "/update",method = RequestMethod.POST)
    @ResponseBody
    public Resp update(E entity){
        if(ParamUtil.isBlank(entity.getId())){
            return new Resp(Resp.PARAM_ERROR,"参数错误，请重试");
        }
        E e = getService().findOne(entity.getId());
        if(e == null){
            return new Resp(Resp.PARAM_ERROR,"查无此数据，请刷新重试");
        }
        //获取Hutool拷贝实例
        CopyOptions copyOptions = CopyOptions.create();
        //忽略为null值得属性
        copyOptions.setIgnoreNullValue(true);
        //进行属性拷贝
        BeanUtil.copyProperties(entity,e,copyOptions);
        //对实体类中的@validation注解进行校验
        Medusa medusa = Message.getMsg(e);
        if(!medusa.isFlag()){
            return new Resp(Resp.PARAM_ERROR, medusa.getMessage());
        }
        getService().update(e);
        return new Resp("更新成功");
    }

    /**
     * @author zk
     * @Description 通过ids批量删除 此处为物理删除
     * @date 2018-07-19 15:34
     */
    @RequestMapping(value = "/delete",method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public Resp delete(String[] ids){
        List<E> list = getService().findAll(ids);
        for(E e:list){
            getService().delete(e.getId());
            RelationUtil.delRelation(e,em,false);
        }
        return new Resp("删除成功");
    }

    /**
     * @author zk
     * @Description 通过ids批量删除 此处为逻辑删除
     * @date 2018-07-19 15:34
     */
    @RequestMapping(value = "/logical_del",method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public Resp logicalDel(String[] ids){
        List<E> list = getService().findAll(ids);
        for (E e : list) {
            if(e==null){
                continue;
            }
            //进行级联逻辑删除 若无需要可不使用
            RelationUtil.delRelation(e,em,true);
            e.setDelFlag(CommonConstant.DEL_FLAG);
        }
        getService().save(list);
        return new Resp("删除成功");
    }

    /**
     * @author zk
     * @Description 获取下拉菜单id-name形式
     *              所有元素，包括已逻辑删除
     * @date 2018-07-16 14:08
     */
    @RequestMapping(value = "/select_all_item",method = RequestMethod.GET)
    @ResponseBody
    public Resp selectAllItem(){
        Class <E> entityClass = (Class <E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        StringBuilder sb = new StringBuilder();
        sb.append("select new cn.lysj.framework.common.utils.web.SelectItem(a.id,a.name) from ");
        sb.append(entityClass.getSimpleName());
        sb.append(" a");
        Query query = em.createQuery(sb.toString(),SelectItem.class);
        List<E> list = query.getResultList();
        return new Resp(list);
    }

    /**
     * @author zk
     * @Description 获取下拉菜单
     *              获取所有未逻辑删除元素
     * @date 2018-07-16 14:08
     */
    @RequestMapping(value = "/select_item",method = RequestMethod.GET)
    @ResponseBody
    public Resp selectItem(){
        //用于获取泛型E的类名
        Class <E> entityClass = (Class <E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        StringBuilder sb = new StringBuilder();
        sb.append("select new cn.lysj.framework.common.utils.web.SelectItem(a.id,a.name) from ");
        sb.append(entityClass.getSimpleName());
        sb.append(" a where delFlag = ");
        sb.append(CommonConstant.NORMAL_FLAG);
        Query query = em.createQuery(sb.toString(),SelectItem.class);
        List list = query.getResultList();
        return new Resp(list);
    }
}
